#include "libcard.h"

#define MAX_BUF_SIZE		256
#define DEBUG

#define STX 0x02
#define ETX 0x03

typedef struct {
	rf_card* card;
	int uart_fd;
	pthread_mutex_t* card_mutex;
	pthread_t thread_id;
	bool seek_card_flag;//false:退出寻卡 true:开始寻卡
}card_t;

card_t g_card;
int err_count = 0;

int get_valid_bcc(const uint8* buf, const uint32 len)
{
	uint32 index = 0;
	uint8 bcc = 0;
	uint32 data_len = 0;
	uint32 i = 0;

	for(index=0; index<len; index++){
		if(buf[index] == STX)
			break;
	}
	if(index>= len){
		printf("##libcard## get bcc fail, due to trash data!\n");
		return -1;
	}


	index++;
	data_len = (buf[index]<<8) | buf[index+1];
	//    if(data_len > (len-5)){
	//        printf("##libcard## get bcc fail, due to index overstep the boundary, data_len = %d buf[index]=%02x  buf[index+1]=%02x , but frame len-5=%d !!\n",
	//               data_len,buf[index],buf[index+1],len-5);
	//        return -1;
	//    }

	index += 2;
	for(i=0; i<data_len; i++){
		bcc ^= buf[index+i];
	}

	return bcc;
}

uint8 get_tran_data_length(const uint8* buf, const uint32 len)
{
	uint8 data_len = 0;
	uint8 index = 0;

	for(index=0;index<len;index++){
		if(buf[index] == STX)
			break;
	}
	if(index >= len)
		return 0;

	for(;index<len;index++){
		if(buf[index] == ETX)
			break;
		data_len++;
	}

	data_len -= 3;
	return data_len;
}

int is_recv_complete(uint8* buf, int len)
{
	int index = 0;
	uint8 *p = NULL;
	int data_len = 0;

	if(buf == NULL)
		return -1;

	for(index=0; index<len; index++){
		if(buf[index] == STX)
			break;
	}
	if(index >= len)
		return -1;

	p = buf + index;
	data_len = (*(p+1)<<8) | *(p+2);
	p = p+3+data_len+1;

	if(*p == 0x03){
#ifdef DEBUG
		printf("##libcard## data recv complete\n");
#endif
		return 0;
	}
	else{
#ifdef DEBUG
		printf("##libcard## data recv no complete\n");
#endif
		return 1;
	}
}

int uart_send(const int fd, const uint8 *buf, const uint32 len)
{
	int sended = 0;
	int i;

	if((fd<=0) || (buf==NULL) ){
		printf("##libcard## uart send fail,due to para err!\n");
		return -1;
	}

	sended = write(fd, buf, len);
	if( sended <= 0){
		printf("##libcard##--Port send [%d] error.\n ", sended);
		g_card.card->errcode = 1;//通信异常
	}

#ifdef DEBUG
	printf("CARD SEND DATA[%03d] -->", sended);
	for(i=0; i < sended; i++) {
		printf("%02x ", buf[i]);
	}
	printf("\n");
#endif
	return sended;
}

int listen_recv(const int fd, uint8 *buf, int rlen, int timeout)
{
	int len = 0, total_len = 0;
	int count =0;
	int ret;
	int i = 0;
	fd_set fdset;
	int check_ret = -1;
	uint8 *p = NULL;
	struct timeval tm;

	if (fd < 0 || rlen<0 || rlen> MAX_BUF_SIZE){
		printf(" ##libcard## listen_recv fail, due to param err !\n");
		return -1;
	}

	p = buf;
	tm.tv_sec = timeout/1000;
	tm.tv_usec = (timeout%1000)*1000;

	while(count<3)
	{
		FD_ZERO(&fdset);
		FD_SET(fd, &fdset);
		ret = select(fd + 1, &fdset, NULL, NULL, &tm);
		if(ret < 0){
			perror("##libcard## select failued !\n ");
			break;
		}
		else if(ret == 0){
			++count; //timeout
		}
		else if(FD_ISSET(fd, &fdset)){
			rlen = rlen-len;
			if(rlen <= 0)
				break;//buffer已接满

			len = read(fd, buf, rlen);
#ifdef DEBUG
            printf("dataLen=%d :",len);
            for(i=0; i<len; i++)
                printf("%02x ",buf[i]);
            printf("\n");
#endif
			if(len < 0)
				break;

			total_len += len;
			check_ret = is_recv_complete(p,total_len);
			if(check_ret == 0)
				break;
			else if(check_ret == 1){
				buf = p+total_len;
				continue;
			}
			else{
				memset(p,0,total_len);
				printf("##libcard## Recv Trash Data\n");
				break;
			}
		}
	}

	if(total_len <= 0){
#ifdef DEBUG
		printf("##libcard## listen_recv fail: without recv data or recv err!!!\n");
#endif
		return total_len;
	}

	int bcc1 = 0,bcc2 = 0;
	bcc1 = get_valid_bcc(p,total_len);
	bcc2 = p[total_len-2];
#ifdef DEBUG
	printf("CARD RECV DATA[%03d]-->",len);
	for(i=0; i<total_len; i++)
		printf("%02x ",p[i]);
	printf("\n");
	printf("##libcard## card recv data bbc1=%02x, bbc2=%02x\n",bcc1,bcc2);
#endif
	if((bcc1 != bcc2) || (bcc1 == -1))
		return -1;
	return total_len;
}

int port_open(card_uart_para *port)
{
	int fd = 0;
	card_uart_para *com = port;

	if(NULL == com)	return -1;

	//打开串口设备
	fd = open(com->name, O_RDWR|O_NOCTTY|O_NONBLOCK);
	if(fd < 0) {
		printf("##libcard##--Open PORT: [%s] failure.\n", com->name);
	}
	return fd;
}

int speed_to_flag(int speed)
{
	uint32 i;
	int cnt = 0;

	for (i = 0; i < sizeof(speed_arr)/sizeof(int); i++) {
		cnt = (speed - speed_arr[i]);
		if ( cnt == 0)
			return baudflag_arr[i];
	}

	printf("##libcard##--Unsupported baudrate, use 9600 instead!\n");
	return B9600;
}

int port_setup(int fd, card_uart_para *port)
{
	card_uart_para *com = port;
	struct termios old_tio, new_tio;
	int baud_rate = 0;

	if(fd < 0)		return -1;
	if(NULL == com)		return -1;

	tcgetattr(fd, &old_tio);
	bzero(&new_tio, sizeof(struct termios));
	new_tio.c_cflag |= (CLOCAL | CREAD);

	//设置波特率
	baud_rate = speed_to_flag(com->baud);
	new_tio.c_cflag |= baud_rate;
	//设置停止位
	switch(com->stop_bits) {
	case 1:
		new_tio.c_cflag &= ~CSTOPB;
		break;
	case 2:
		new_tio.c_cflag |= CSTOPB;
		break;
	default:
		printf("##libcard##--PORT stop bits set error. use default.\n");
		new_tio.c_cflag &= ~CSTOPB;
		break;
	}

	//设置奇偶校验
	switch(com->parity) {
	case 0://无校验
		new_tio.c_cflag &= ~PARENB;
		break;
	case 1://奇校验
		new_tio.c_cflag |= (PARENB | PARODD);
		break;
	case 2://偶校验
		new_tio.c_cflag |= PARENB;
		new_tio.c_cflag &= ~PARODD;
		break;
	case 3://MARK校验
		new_tio.c_cflag |= (PARENB | PARODD);
		new_tio.c_cflag |= CMSPAR;
		break;
	case 4://SPACE校验
		new_tio.c_cflag |= PARENB;
		new_tio.c_cflag &= ~PARODD;
		new_tio.c_cflag |= CMSPAR;
		break;
	default:
		printf("##libcard##--PORT parity set error. use default.\n");
		new_tio.c_cflag &= ~PARENB;
		break;
	}
	new_tio.c_cflag &= ~CSIZE;
	switch(com->data_bits) {
	case 5:
		new_tio.c_cflag |= CS5;
		break;
	case 6:
		new_tio.c_cflag |= CS6;
		break;
	case 7:
		new_tio.c_cflag |= CS7;
		break;
	case 8:
		new_tio.c_cflag |= CS8;
		break;
	default:
		printf("##libcard##--PORT data bits set error. use default.\n");
		new_tio.c_cflag |= CS8;
		break;
	}

	//设置无硬件流控
	new_tio.c_cflag &= ~CRTSCTS;
	new_tio.c_lflag = 0;
	new_tio.c_oflag = 0;
	new_tio.c_cc[VMIN] = 1;
	new_tio.c_cc[VTIME] = 0;
	new_tio.c_iflag &= ~(IXON | IXOFF | IXANY);

	cfsetispeed(&new_tio, baud_rate);
	cfsetospeed(&new_tio, baud_rate);
	tcsetattr(fd, TCSANOW, &new_tio);
	tcflush(fd, TCIFLUSH);

	return 0;
}

void setTimer(unsigned int seconds, unsigned int mseconds)
{
	struct timeval temp;

	temp.tv_sec = seconds + (mseconds/1000);
	temp.tv_usec = (mseconds%1000)*1000;

	select(0, NULL, NULL, NULL, &temp);

	return ;
}

//检查版本,同时检测读卡器的通信是否断开
void* protocol_check_ver(void* arg)
{
	uint8 cmd[7] = {0x02,0x00,0x02,0x31,0x11,0x20,0x03};
	uint8 data[MAX_BUF_SIZE] = {0};

	int re_len = 0;
	int index = 0;

	while(1){
		printf("##libcard## check card version state: errcode=%02d \n",g_card.card->errcode);

		memset(data,0,sizeof(data));
		setTimer(1,0);

		pthread_mutex_lock(g_card.card_mutex);
		if((uart_send(g_card.uart_fd, cmd, sizeof(cmd))) < 0){
			printf("##libcard## check card versio  send error\n");
			g_card.card->errcode = 1;//通信异常
			pthread_mutex_unlock(g_card.card_mutex);
			continue;
		}

		re_len = listen_recv(g_card.uart_fd, data, sizeof(data),1000);
		if(re_len <= 0){
			if(err_count >= 3){
				printf("##libcard## check card versio listen_recv timeout or error!\n");
				g_card.card->errcode = 1;//通信异常
				err_count = 0;
			}
			err_count++;
			pthread_mutex_unlock(g_card.card_mutex);

			continue;
		}

		for(index=0; index<re_len;index++){
			if(data[index] == STX)
				break;
		}

		if((data[index+3] != 0x00) || data[index+4] != 0x00){
			if(err_count > 3){
				g_card.card->errcode = 1;//连续3次检查版本失败，通信异常
				printf("##libcard## check card version , card reponse error, errcode=%02d !\n",g_card.card->errcode);
				err_count = 0;
			}

			err_count++;
			pthread_mutex_unlock(g_card.card_mutex);
			continue;
		}

		g_card.card->errcode = 0;//通信正常
		err_count = 0;

		pthread_mutex_unlock(g_card.card_mutex);
	}

	return NULL;
}

//初始化函数，pcard指向一个rf_card结构， plock指向pthread_mutex_t互斥量, 指向sem_t信号量,在检测到刷卡时置位。//返回0成功，1 失败
int protocol_card_init(void * pcard, void *plock, void *psem)
{
	int fd = 0;

	if((pcard==NULL) || (plock==NULL) || (psem==NULL)){
		printf("##libcard error## card init fail, due to init para NULL!\n");
		return 1;
	}

	g_card.card = (rf_card*)pcard;
	g_card.card_mutex=(pthread_mutex_t*)plock;

	if((fd = port_open(&(g_card.card->com))) == -1 )
	{
		printf("##libcard error## open device fail\n");
		return 1;
	}

	g_card.uart_fd = fd;
	port_setup(g_card.uart_fd,&(g_card.card->com));
	pthread_create(&g_card.thread_id,NULL,protocol_check_ver,NULL);

	printf("##libcard Init##uart name:%s uart baud:%d uart data_bit:%d uart parity:%d uart stop_bits:%d \n",g_card.card->com.name, g_card.card->com.baud,
			g_card.card->com.data_bits, g_card.card->com.parity, g_card.card->com.stop_bits);
	printf("##libcard Init## card source pointer:%p   libcard card pointer:%p \n",pcard,(g_card.card));

	return 0;
}


//激活卡函数，delaytime 等待时间，cardtype 返回的卡类型，UIDLen返回的卡号长度，cardUID指向一个32字节大小的内存，用于存储返回的卡号。
int protocol_enabled_card(short delaytime, char *cardtype, unsigned char *UIDLen, char * cardUID) //返回0成功，1 失败
{
	int count = 0;
	uint8 cmd[] = {0x02,0x00,0x04,0x32,0x24,0x00,0x00,0x16,0x03};
	uint8 data[MAX_BUF_SIZE]={0};
	int len = 0, index = 0, i = 0;
	unsigned int delay = (unsigned int)delaytime;

	printf("##libcard## begin enable card...\n");

	while(count < 60)//如果连续60次没有探测到卡则退出
	{
		if(g_card.seek_card_flag != true){
			printf("##libcard## exit seek card status!\n");
			return 1;
		}

		pthread_mutex_lock(g_card.card_mutex);

		memset(data,0,sizeof(data));
		setTimer(0,delay);
		if((uart_send(g_card.uart_fd,cmd,sizeof(cmd))) < 0 )
		{
			printf("##libcard## enable card  send error\n");
			count++;
			if(err_count >= 3){
				g_card.card->errcode = 1;//通信异常
				err_count = 0;
				goto  FAIL;
			}

			pthread_mutex_unlock(g_card.card_mutex);
			continue;
		}

		if((len = listen_recv(g_card.uart_fd, data, sizeof(data), 1000)) <= 0)
		{
			printf("##libcard## enable card  recv error\n");
			count++;
			if(err_count >= 3){
				g_card.card->errcode = 1;//通信异常
				err_count = 0;
				goto FAIL;
			}
			err_count++;
			pthread_mutex_unlock(g_card.card_mutex);
			continue;
		}

		for(index=0; index<len; index++){
			if(data[index] == STX)
				break;
		}

		if(data[index+3] == 0x30 &&  data[index+4] == 0x06)//等待卡进入感应区超时
		{
			printf("##libcard## wait card enter induction zone outtime count=%d\n",count);
			count++;
			pthread_mutex_unlock(g_card.card_mutex);
			continue;
		}
		else if(data[index+3] == 0x30 && data[index+4] == 0x05)//激活失败
		{
			printf("##libcard## enable card fail!!!\n");
			pthread_mutex_unlock(g_card.card_mutex);
			return 1;
		}
		else if(data[index+3] == 0x00 && data[index+4] == 0x00)//激活成功
		{
			printf("##libcard## enable card success.\n");
			g_card.card->cardtype = data[index+5];
			*cardtype = data[index+5];
			printf("---cardtype = %0x\n",g_card.card->cardtype);
			*UIDLen = data[index+6];
			g_card.card->UIDLen = data[index+6];
			for(i=0;i<g_card.card->UIDLen;i++)
				g_card.card->cardUID[i] = data[index+7+i];
			memcpy(cardUID,g_card.card->cardUID,g_card.card->UIDLen);

			pthread_mutex_unlock(g_card.card_mutex);
			return 0;
		}
		else{
			printf("##libcard##card enter induction zone enable error, count=%d\n",count);
			count++;
			pthread_mutex_unlock(g_card.card_mutex);
			continue;

		}
	}

	if(count >= 60)
	{
		printf("##libcard## enable card fail count > 60!!!\n");
		//        pthread_mutex_unlock(g_card.card_mutex);
		return 1;
	}

FAIL:
	printf("##libcard## enable card fail  ,errode=%d !!!\n",g_card.card->errcode);
	pthread_mutex_unlock(g_card.card_mutex);
	return 1;

}

void clear_card_info(void)
{
	memset(&(g_card.card->UIDLen),0,sizeof(unsigned char));
	memset(g_card.card->cardUID,0,sizeof(g_card.card->cardUID));
	memset(g_card.card->cmd1,0,sizeof(g_card.card->cmd1));
	memset(g_card.card->cmd2,0,sizeof(g_card.card->cmd2));
	memset(g_card.card->cmd3,0,sizeof(g_card.card->cmd3));
	memset(g_card.card->cardNUM,0,sizeof(g_card.card->cardNUM));
	memset(&(g_card.card->available_money),0,sizeof(unsigned int));
	memset(&(g_card.card->ver),0,sizeof(char));
	memset(&(g_card.card->tag),0,sizeof(char));
	memset(&(g_card.card->rand),0,sizeof(int));
	memset(&(g_card.card->mac),0,sizeof(int));
}

//读卡查询函数，money 返回卡余额，locknum 返回灰锁次数。
int protocol_read_card(float *money, char *locknum) //返回0成功，1 失败
{
	short delaytime = 250;
	int re_len = 0;
	int i = 0, j = 0;
	char cardtype[1]={0};
	unsigned char UIDLen[1]={0};
	char cardUID[64]={0};
	unsigned char data[MAX_BUF_SIZE];
	int index = 0;

	clear_card_info();
	g_card.seek_card_flag = true;

	setTimer(1,0);
	printf("##libcard## begin read card...\n");
	if (g_card.card->errcode  !=  0){
		printf("##libcard## read card fail, due to card is err! errcode=%d\n",g_card.card->errcode);
		return 1;
	}

	if(protocol_enabled_card(delaytime,cardtype,UIDLen,cardUID) == 1){
		printf("##libcard## read card  fail ,due to enable card fail\n");
		clear_card_info();
		return 1;
	}
	else
	{
		pthread_mutex_lock(g_card.card_mutex);

#ifdef NW_CARD
		uint8 cmd1[]={0x02,0x00,0x08,0x32,0x26,0xFF,0x00,0xB0,0x81,0x00,0x08,0xD2,0x03 };
		uint8 cmd2[] = {0x02,0x00,0x05,0x31,0x13,0x00,0xC8,0x01,0xEB,0x03};

		if(uart_send(g_card.uart_fd, cmd1, sizeof(cmd1)) < 0){
			printf("##libcard##  read nw card fail, due to send cmd1 error\n");
			goto fail;
		}

		memset(data,0,sizeof(data));
		re_len = listen_recv(g_card.uart_fd, data, sizeof(data), 1000);
		if(re_len <= 0){
			printf("##libcard## read nw card fail, due to recv data1 error!\n");
			goto fail;
		}
		else{
			for(index=0;index<re_len;index++){
				if(data[index] == STX)
					break;
			}

			if((data[index+3] == 0x00) && (data[index+4] == 0x00)){
				index+=5;
				for(i=0;i<7;i++)
					g_card.card->cardNUM[i+1] = data[index+i];
				g_card.card->cardNUM[0] = 0x00;
			}
			else
				goto fail;
		}

		if(uart_send(g_card.uart_fd, cmd2, sizeof(cmd2)) < 0){
			printf("##libcard##  read nw card fail, due to send cmd2 error\n");
			goto fail;
		}

		memset(data,0,sizeof(data));
		re_len = listen_recv(g_card.uart_fd, data, sizeof(data), 1000);
		if(re_len <= 0){
			printf("##libcard## read nw card fail, due to recv data2 error!\n");
			goto fail;
		}
#endif

#ifdef GW_CARD
		int recLen = 0;
		/*对读卡器ESAM操作*/
		unsigned char cmd_1[] = {0x02,0x00,0x0A,0x32,0x26,0xFF,0x00,0xA4,0x00,0x00,0x02,0xDF,0x02,0x90,0x03};
		unsigned char cmd_2[] = {0x02,0x00,0x08,0x32,0x26,0xFF,0x00,0xB0,0x95,0x18,0x04,0xD2,0x03};
		unsigned char cmd_3[] = {0x02,0x00,0x08,0x32,0x26,0xFF,0x00,0xB0,0x85,0x00,0x15,0xCB,0x03};
		unsigned char cmd_4[] = {0x02,0x00,0x0B,0x32,0x26,0xFF,0x00,0x20,0x00,0x00,0x03,0x12,0x34,0x56,0xB8,0x03};
		unsigned char cmd_5[] = {0x02,0x00,0x08,0x32,0x26,0xFF,0xE0,0xCA,0x00,0x00,0x27,0xE6,0x03};
		unsigned char cmd_6[] = {0x02,0x00,0x08,0x32,0x26,0xFF,0xE0,0xCC,0x00,0x00,0x07,0xC0,0x03};
		//对ESAM第一次操作
		if(uart_send(g_card.uart_fd, cmd_1, sizeof(cmd_1)) < 0){
			printf("##libcard## read card send cmd_1 error\n");
			goto fail;
		}

		memset(data,0,sizeof(data));
		setTimer(0,delaytime);
		recLen = listen_recv(g_card.uart_fd, data, sizeof(data), 1000);
		if((recLen <= 0) || (data[0] != 0x02)){
			printf("##libcard## read gw card recv data_1 error\n");
			goto fail;
		}
		else
		{
			for(i=0; i<recLen;i++)
				if((data[i]==0x9F) && (data[i+1]==0x0C))//查找FCI
					break;
			i += 3;
			g_card.card->ver = data[i+9]; //保存密匙版本
			//for(j=0; j<10; j++)
			//	g_card.card->cardNUM[j] = data[i+10+j];//保存用户卡卡号

			//for(j=0; j<4; j++)
			//card_info->card_handle_date[j] = data[i+20+j];//保存办充电卡理日期
		}

		//对ESAM第二次操作
		if(uart_send(g_card.uart_fd, cmd_2, sizeof(cmd_2)) < 0){
			printf("##libcard## read gw card send cmd_2 error\n");
			goto fail;
		}

		memset(data, 0, sizeof(data));
		setTimer(0,delaytime);
		recLen = listen_recv(g_card.uart_fd, data, sizeof(data), 1000);
		if((recLen <= 0) || (data[0] != 0x02)){
			printf("##libcard## read gw card recv data_2 error\n");
			goto fail;
		}
		else
		{
			//for(i=0; i<4; i++)
			//	card_info->card_vailed_data[i] = data[i+5];//保存用户卡的有效期
			;
		}

		//对ESAM第三次操作
		if(uart_send(g_card.uart_fd, cmd_3, sizeof(cmd_3)) < 0){
			printf("##libcard## read gw card send cmd_3 error\n");
			goto fail;
		}
		memset(data,0,sizeof(data));
		setTimer(0,delaytime);
		recLen = listen_recv(g_card.uart_fd, data, sizeof(data),1000);
		if((recLen <= 15) || (data[0] != 0x02) ){
			printf("##libcard## read gw card recv data_3 error, length error!\n");
			goto fail;
		}
		else
		{
			for(i=0; i<8; i++)
				g_card.card->cardNUM[i] = data[i+6];//保存支付卡卡号
		}

		//对ESAM第四次操作
		if(uart_send(g_card.uart_fd, cmd_4, sizeof(cmd_4)) < 0){
			printf("##libcard## read gw card send cmd_4 error\n");
			goto fail;
		}

		memset(data,0,sizeof(data));
		setTimer(0,delaytime);
		if(listen_recv(g_card.uart_fd, data, sizeof(data),1000) < 0){
			printf("##libcard## read  gw card recv data_4 error\n");
			goto fail;
		}
		else
			;

		if(uart_send(g_card.uart_fd, cmd_5, sizeof(cmd_5)) < 0)//对ESAM第五次操作
		{
			printf("##libcard## read gw card send cmd_5 error\n");
			goto fail;
		}
		memset(data,0,sizeof(data));
		setTimer(0,delaytime);
		recLen = listen_recv(g_card.uart_fd, data, sizeof(data), 1000);
		if((recLen <= 0) || (data[0] != 0x02)){
			printf("##libcard## read gw card recv data_5 error\n");
			goto fail;
		}
		else
		{
			if((data[recLen-4] == 0x69) && (data[recLen-3] == 0x85))//如果没有异常灰锁
			{
				//card_info->card_err_locknum = 0;//保存灰锁次数
				;
			}
			else if((data[recLen-4] == 0x90) && (data[recLen-3] == 0x00))//如果卡片被锁过
			{
				//	card_info->card_frozen_amount = ((data[5]<<24) | (data[6]<<16) | (data[7]<<8) | data[8]);
				//	card_info->card_frozen_amount = card_info->card_frozen_amount / 100;//保存冻结卡内余额

				//保存卡内ET余额
				g_card.card->available_money = ((data[12]<<24) | (data[13]<<16) | (data[14]<<8) | data[15]);
				//card_info->ET_balance = card_info->ET_balance / 100;//保存卡内ET余额

				//for(i=0; i<4; i++)
				//	card_info->card_ET_balance[i] = data[12+i];//保存ET余额

				//for(i=0; i<2; i++)
				//	card_info->card_ET_tran_serial_num[i] = data[16+i];//保存卡内ET交易序号

				//for(i=0; i<4; i++)
				//	card_info->last_tran_date[i] = data[24+i];//保存上次交易日期

				//for(i=0; i<3; i++)
				//	card_info->last_tran_time[i] = data[28+i];//保存上次交易时间

				//card_info->card_err_locknum = data[recLen-5];//保存异常灰锁次数
			}
		}

		if(uart_send(g_card.uart_fd, cmd_6, sizeof(cmd_6)) < 0)//对ESAM第六次操作
		{
			printf("##libcard## read gw card send cmd_6 error\n");
			goto fail;
		}
		memset(data,0,sizeof(data));
		setTimer(0,delaytime);
		if((recLen = listen_recv(g_card.uart_fd,data,sizeof(data), 1000)) < 0)
		{
			printf("##libcard## read gw card recv data_6 error\n");
			goto fail;
		}
		else
		{
			//card_info->card_money = ((data[5]<<24) | (data[6]<<16) | (data[7]<<8) | data[8]);
			//card_info->card_money = card_info->card_money / 100;//保存冻结卡内余额
			;
		}

#endif

		printf("############ Card Info ##################\n");
		printf("card.type = %x\n",g_card.card->cardtype);
		printf("card.UIDLen = %d\n",g_card.card->UIDLen);
		printf("card.cardUID = ");
		for(i=0; i<g_card.card->UIDLen; i++)
			printf("%02x ", g_card.card->cardUID[i]);
		printf("\n");

		printf("card.cardNUM = ");
		for(i=0; i<8; i++)
			printf("%02x",g_card.card->cardNUM[i]);
		printf("\n");
		printf("card.ver = %02x\n",g_card.card->ver);
		printf("card.money = %d\n",g_card.card->available_money);
		printf("############    Card  End ##################\n");


	}
	pthread_mutex_unlock(g_card.card_mutex);
	return 0;

	fail:
	clear_card_info();
	pthread_mutex_unlock(g_card.card_mutex);
	return 1;
}


int protocol_exit_seek_card_status(void)
{
	g_card.seek_card_flag = false;
	return 0;
}
